import { createTaskQueue, arrified, createStateNode, getTag } from "../Misc";

const taskQueue = createTaskQueue()

let subTask = null // 默认没有任务
let pendingCommit = null
const commitAllWork = fiber => {
  fiber.effects.forEach(item => {
    if (item.effectTag === 'placement') {
      item.parent.stateNode.appendChild(item.stateNode)
    }
  })
}
const getFirstTask = () => {
  /**
   * 从任务队列中获取任务
   */
  const task = taskQueue.pop() // 队列，先进先出
  /**
   * 返回最外层节点的fiber对象
   */
  return {
    props: task.props || [],
    stateNode: task.dom,
    tag: "host_root",
    effects: [],
    child: null
  }
}

const reconcileChildren = (fiber, children) => {
  /**
   * children: object | array
   */
  const reconcileChildren = arrified(children)

  let index = 0
  let numberOfElements = reconcileChildren.length // 代表数组中元素的个数
  let element = null
  let newFiber = null
  let prevFiber = null
  while (index < numberOfElements) {
    element = reconcileChildren[index]
    newFiber = {
      type: element.type,
      props: element.props,
      tag: getTag(element),
      effects: [],
      effectTag: 'placement',
      stateNode: null,
      parent: fiber
    }
    newFiber.stateNode = createStateNode(newFiber)

    if (index === 0) {
      fiber.child = newFiber
    } else if (element) {
      prevFiber.sibling = newFiber
    }
    prevFiber = newFiber
    index++
  }

}


const executeTask = fiber => {
  reconcileChildren(fiber, fiber.props.children)
  if (fiber.child) return fiber.child
  let currentExecutelyFiber = fiber
  while (currentExecutelyFiber.parent) {
    currentExecutelyFiber.parent.effects = currentExecutelyFiber.parent.effects.concat(currentExecutelyFiber.effects.concat([currentExecutelyFiber]))
    if (currentExecutelyFiber.sibling) {
      return currentExecutelyFiber.sibling
    }
    currentExecutelyFiber = currentExecutelyFiber.parent
  }
  console.log(fiber);
  pendingCommit = currentExecutelyFiber
}

const workLoop = deadline => {
  /**
   * 如果子任务不存在，获取子任务
   */
  if (!subTask) {
    subTask = getFirstTask()
  }
  /**
   * 如果任务存在并且浏览器有空余时间就调用
   * executeTask 方法执行任务 接受任务 返回新的任务
   */
  while (subTask && deadline.timeRemaining() > 1) {
    subTask = executeTask(subTask)
  }

  if (pendingCommit) {
    commitAllWork(pendingCommit)
  }
}

const performTask = deadline => {
  // 执行任务
  workLoop(deadline)
  /**
   * 判断任务是否存在
   * 判断任务队列中是否还有任务没执行
   * 如果有，再告诉浏览器在空闲时间执行
   */
  if (subTask || !taskQueue.isEmpty()) {
    requestIdleCallback(performTask)
  }
}
export const render = (element, dom) => {
  /**
   * 1. 向任务队列中添加任务（任务就是通过 vdom 对象构建 fiber 对象）
   * 2. 指定在浏览器空闲时执行任务
   */
  taskQueue.push({
    dom,
    props: { children: element }
  })
  // 指定在浏览器空闲时间执行任务
  requestIdleCallback(performTask)
}